package com.mazaiting.instructions.references;

import com.mazaiting.instructions.base.Index16Instruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtOperandStack;
import com.mazaiting.rtda.heap.MtConstant;
import com.mazaiting.rtda.heap.MtConstantPool;

import java.util.Objects;

/**
 * 虚拟指令
 *
 * @author mazaiting
 * @since 2021/8/18
 */
public class InvokeInstruction {

    public static class InvokeSpecial extends Index16Instruction {
        @Override
        public void execute(MtFrame frame) {
            frame.getOperandStack().popRef();
        }

        @Override
        public String toString() {
            return "invokespecial " + index;
        }
    }

    public static class InvokeVirtual extends Index16Instruction {
        @Override
        public void execute(MtFrame frame) {
            MtConstantPool pool = frame.getMethod().getMtClass().getConstantPool();
            MtConstant.MtMethodRef methodRef = (MtConstant.MtMethodRef) pool.getConstant(index);
            if (Objects.equals(methodRef.getName(), "println")) {
                MtOperandStack stack = frame.getOperandStack();
                switch (methodRef.getDescriptor()) {
                    case "(Z)V":
                        System.out.println(stack.popInt() != 0);
                        break;
                    case "(C)V":
                        System.out.println((char) stack.popInt());
                        break;
                    case "(I)V":
                    case "(B)V":
                    case "(S)V":
                        System.out.println(stack.popInt());
                        break;
                    case "(F)V":
                        System.out.println(stack.popFloat());
                    case "(J)V":
                        System.out.println(stack.popLong());
                        break;
                    case "(D)V":
                        System.out.println(stack.popDouble());
                        break;
                    default:
                        System.out.println("println: " + methodRef.getDescriptor());
                        break;
                }
                stack.popRef();
            }
        }

        @Override
        public String toString() {
            return "invokevirtual " + index;
        }
    }
}


















